/**
 * 日期时间处理工具类
 *
 * @author veblen
 * @version V1.0, 2013-09-05
 */
var DateUtil = {

    /**
     * 比较两个日期的大小。
     *
     * @param date1
     *            日期对象或者满足日期格式的日期字符串
     * @param date2
     *            日期对象或者满足日期格式的日期字符串
     * @return -1:date1 < date2 ; 0:date1=date2 ; 1:date1>date2
     */
    compare: function (date1, date2) {
        var days = Date.parse(date1) - Date.parse(date2);
        if (days > 0) {
            return 1;
        } else if (days < 0) {
            return -1;
        }
        return 0;
    },

    /**
     * 去掉日期中的时间，保留日期。
     *
     * @param date
     *            需要截取的时间
     * @param dateSepartor
     *            日期分隔符
     * @param timeSepartor
     *            时间分隔符
     * @return 天数
     */
    splitTime: function (date, dateSepartor, timeSepartor) {

        if (date instanceof Date) {
            date.setHours(0);
            date.setMinutes(0);
            date.setSeconds(0);
        } else if (typeof(date) == "string") {

            // 如果是字符串，则转成日期，在进行转换。
            date = this.strToDate(date, dateSepartor, timeSepartor);
            date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
        } else {
            throw Error("转换日期失败:原因date为" + date);
        }
        return date;
    },

    /**
     * 获取两个日期相差的天数，若不满足一天则按照一天计算
     *
     * @param date1
     *            日期对象或者满足日期格式的日期字符串
     * @param date2
     *            日期对象或者满足日期格式的日期字符串
     * @param dateSepartor
     *            日期分隔符
     * @param timeSepartor
     *            时间分隔符
     * @return 天数
     */
    getDays: function (date1, date2, dateSepartor, timeSepartor) {
        date1 = this.splitTime(date1, dateSepartor, timeSepartor);
        date2 = this.splitTime(date2, dateSepartor, timeSepartor);
        var days = Date.parse(date1) - Date.parse(date2);
        days = parseInt(days / (1000 * 60 * 60 * 24));
        return Math.abs(days);
    },

    /**
     * 判断该年份是否为闰年。
     *
     * @param year
     *            年份
     * @return true：闰年 ; false：非闰年
     */
    isLeapYear: function (year) {

        // 判断传入year是否为整数
        if ((/^\d+$|-\d+$/).test(year)) {
            return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
        }
        throw new Error("参数" + year + "必须能被转换为整数!");
    },

    /**
     * 日期字符串转换成日期对象。
     *
     * @param dateStr
     *            满足日期格式的日期字符串，格式如下：yyyy-MM-dd、yyyy-MM-dd
     *            hh:mm:ss、yyyy/MM/dd、yyyy/MM/dd hh:mm:ss
     * @param dateSepartor
     *            日期分隔符
     * @param timeSepartor
     *            时间分隔符
     * @return 日期对象
     */
    strToDate: function (dateStr, dateSepartor, timeSepartor) {
        var strArray = dateStr.split(" ");

        // 如果传入参数中带有时间分隔符，则用分隔符进行分隔
        var strDate;
        if (dateSepartor) {
            strDate = strArray[0].split(dateSepartor);
        } else {

            // 默认情况下认为分隔符是减号"-"。
            strDate = strArray[0].split("-");
        }

        // 如果传入dateStr中带有时间，则返回带有时间的时间对象
        var date;
        if (strArray[1]) {

            // 解析时间
            var strTime;
            if (timeSepartor) {
                strTime = strArray[1].split(timeSepartor);
            } else {

                // 默认认为时间分隔符为冒号":"
                strTime = strArray[1].split(":");
            }
            date = new Date(strDate[0], (strDate[1] - parseInt(1)), strDate[2],
                strTime[0], strTime[1], strTime[2]);
        } else {
            date = new Date(strDate[0], (strDate[1] - parseInt(1)), strDate[2]);
        }
        return date;
    },

    /**
     * 根据指定的日期格式获取当前日期字符串。 年份 : YYYY/yyyy/YY/yy； 月份 : MM/M： 日期 : dd/d/； 时间 :
     * hh/h/ 时间； 分钟 : mm/m； 秒 : ss/SS/s/S。
     *
     * @param date
     *            日期
     * @param format
     *            格式化字符串
     * @return 日期字符串
     */
    format: function (date, format) {
        var z = {
            y: date.getFullYear(),
            M: date.getMonth() + 1,
            d: date.getDate(),
            h: date.getHours(),
            m: date.getMinutes(),
            s: date.getSeconds()
        };
        return format.replace(/(y+|M+|d+|h+|m+|s+)/g, function (v) {
            return ((v.length > 1 ? "0" : "") + eval('z.' + v.slice(-1)))
                .slice(-(v.length > 2 ? v.length : 2));
        });
    },
    add: function (date, field, number) {
        var fields = "ymdhns";
        //将传入field转为小写，判断是否在"ymwdhns"中。
        var index = fields.indexOf(field.toLocaleLowerCase());
        if (index != -1) {
            if ("y" == field) {
                date.setFullYear(date.getFullYear() + parseInt(number));
            }
            if ("m" == field) {
                date.setMonth(date.getMonth() + parseInt(number));
            }
            if ("d" == field) {
                date.setDate(date.getDate() + parseInt(number));
            }
            if ("h" == field) {
                date.setHours(date.getHours() + parseInt(number));
            }
            if ("n" == field) {
                date.setMinutes(date.getMinutes() + parseInt(number));
            }
            if ("s" == field) {
                date.setSeconds(date.getSeconds() + parseInt(number));
            }
        } else {
            throw Error("不支持的日期字段：" + field);
        }
    },
    /**
     * 毫秒转时间
     * @param duration
     * @returns {string}
     */
    msToTime: function (duration) {
        var milliseconds = parseInt((duration % 1000) / 100)
            , seconds = parseInt((duration / 1000) % 60)
            , minutes = parseInt((duration / (1000 * 60)) % 60)
            , hours = parseInt((duration / (1000 * 60 * 60)) % 24);

        hours = (hours < 10) ? "0" + hours : hours;
        minutes = (minutes < 10) ? "0" + minutes : minutes;
        seconds = (seconds < 10) ? "0" + seconds : seconds;

        return hours + ":" + minutes + ":" + seconds + "." + milliseconds;
    },
    msToSimpleTime: function (duration) {
        var milliseconds = parseInt((duration % 1000) / 100)
            , seconds = parseInt((duration / 1000) % 60)
            , minutes = parseInt((duration / (1000 * 60)) % 60)
            , hours = parseInt((duration / (1000 * 60 * 60)) % 24);

        hours = (hours < 10) ? "0" + hours : hours;
        minutes = (minutes < 10) ? "0" + minutes : minutes;
        seconds = (seconds < 10) ? "0" + seconds : seconds;
        if (milliseconds <= 1000) {
            return milliseconds + "毫秒";
        } else if (milliseconds < 60000) {
            return minutes + "秒:" + milliseconds + "毫秒"
        } else if (milliseconds < 60000 * 60) {
            return minutes + "分钟:" + seconds + "秒:" + milliseconds + "毫秒"
        } else {
            return hours + "小时:" + minutes + "分钟:" + seconds + "秒:" + milliseconds + "毫秒"
        }
    },
    /**
     * 毫秒型的时间转时分秒
     * @param second
     * @param displaycount
     * @returns {*}
     * @constructor
     */
    MillisecondToDate: function (second, displaycount) {
        if (!second) {
            return 0;
        }
        var time = '';
        if (second >= 24 * 3600) {
            //time += parseInt(second / 24 * 3600) + '天';
            time += parseInt(second / 24 * 3600) + ':';
            second %= 24 * 3600;
        }
        if (second >= 3600) {
            //time += parseInt(second / 3600) + '小时';
            time += parseInt(second / 3600) + ':';
            second %= 3600;
        }
        if (second >= 60) {
//	        time += parseInt(second / 60) + '分钟';
            time += parseInt(second / 60) + ':';
            second %= 60;
        }
        if (second > 0) {
            //time += second + '秒';
            time += second;
        }
        var arr = time.split(":");
        var day = "", h = "", min = "", sec = "";
        var str = "";
        if (arr.length == 1) {
            sec = arr[0] < 10 ? "0" + arr[0] : arr[0];
            str = displaycount == 4 ? ("00:00:00:" + sec) : ("00:00:" + sec);
        }
        if (arr.length == 2) {
            min = arr[0] < 10 ? "0" + arr[0] : arr[0];
            sec = arr[1] < 10 ? "0" + arr[1] : arr[1];
            str = displaycount == 4 ? ("00:00:" + min + ":" + sec) : ("00:" + min + ":" + sec);
        }
        if (arr.length == 3) {
            h = arr[0] < 10 ? "0" + arr[0] : arr[0];
            min = arr[1] < 10 ? "0" + arr[1] : arr[1];
            sec = arr[2] < 10 ? "0" + arr[2] : arr[2];
            str = displaycount == 4 ? ("00:" + h + ":" + min + ":" + sec) : (h + ":" + min + ":" + sec);
        }
        if (arr.length == 4) {
            day = arr[0] < 10 ? "0" + arr[0] : arr[0];
            h = arr[1] < 10 ? "0" + arr[1] : arr[1];
            min = arr[2] < 10 ? "0" + arr[2] : arr[2];
            sec = arr[3] < 10 ? "0" + arr[3] : arr[3];
            str = displaycount == 4 ? (day + ":" + h + ":" + min + ":" + sec) : h + ":" + min + ":" + sec;
        }
        return str;
    }
};

/**
 * 判断该日期所属年份是否为闰年
 *
 * @return true：闰年 ； false：非闰年
 */
Date.prototype.isLeapYear = function () {
    var year = this.getFullYear();
    if ((/^\d+$|-\d+$/).test(year)) {
        return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
    }
};

/**
 * 根据指定的日期格式获取当前日期字符串。 年份 : YYYY/yyyy/YY/yy； 月份 : MM/M： 星期 : W/w； 日期 :
 * dd/DD/d/D； 时间 : hh/HH/h/H 时间； 分钟 : mm/m； 秒 : ss/SS/s/S。
 *
 * @param format
 *            格式化字符串
 * @return 日期字符串
 */
Date.prototype.format = function (format) {
    var z = {
        y: this.getFullYear(),
        M: this.getMonth() + 1,
        d: this.getDate(),
        h: this.getHours(),
        m: this.getMinutes(),
        s: this.getSeconds()
    };
    return format.replace(/(y+|M+|d+|h+|m+|s+)/g, function (v) {
        return ((v.length > 1 ? "0" : "") + eval('z.' + v.slice(-1)))
            .slice(-(v.length > 2 ? v.length : 2));
    });
};

/**
 * 日期计算，根据指定的字段进行计算，字段t如下： y : 年； m ：月； d ：日； h ：时； n ：分； s ：秒。
 * number为正数，则表示结果在该日期之后； number为负数，则表示结果在该日期之前。
 *
 * @param field
 *            日期字段
 * @param number
 *            所需要相加的数值
 */
Date.prototype.add = function (field, number) {
    var fields = "ymdhns";

    // 将传入field转为小写，判断是否在"ymwdhns"中。
    var index = fields.indexOf(field.toLocaleLowerCase());
    if (index != -1) {
        if ("y" == field) {
            this.setFullYear(this.getFullYear() + parseInt(number));
        }
        if ("m" == field) {
            this.setMonth(this.getMonth() + parseInt(number));
        }
        if ("d" == field) {
            this.setDate(this.getDate() + parseInt(number));
        }
        if ("h" == field) {
            this.setHours(this.getHours() + parseInt(number));
        }
        if ("n" == field) {
            this.setMinutes(this.getMinutes() + parseInt(number));
        }
        if ("s" == field) {
            this.setSeconds(this.getSeconds() + parseInt(number));
        }
    } else {
        throw Error("不支持的日期字段：" + field);
    }
};

/**
 * 根据指定的字段获取该Date对象与传入的endDate的差值，字段field如下： y ：年； m ：月； d ：日； h ：时； n ：分； s ：秒。
 *
 * @param field
 *            字段
 * @param otherDate
 *            日期对象，必须为日期对象，否则会抛出异常。
 * @return 返回具体的差值，如：20,12等。
 */
Date.prototype.diff = function (field, otherDate) {
    var fields = "ymdhns";
    if (otherDate instanceof Date) {

        // 将传入field转为小写，判断是否在"ymwdhns"中。
        var index = fields.indexOf(field.toLocaleLowerCase());
        if (index != -1) {
            if ("y" == field) {
                return Math.abs(this.getFullYear() - otherDate.getFullYear());
            }
            if ("m" == field) {
                return Math.abs(otherDate.getFullYear() * 12 + otherDate.getMonth() - this.getFullYear() * 12 - this.getMonth());
            }

            // 计算两个日期相差毫秒数。
            var diffMillis = otherDate.getTime() - this.getTime();
            if ("d" == field) {
                return Math.abs(Math.floor(diffMillis / (24 * 3600 * 1000)));
            }

            // 计算天数
            diffMillis = diffMillis % (24 * 3600 * 1000);
            if ("h" == field) {
                return Math.abs(Math.floor(diffMillis / (3600 * 1000)));
            }

            // 计算小时数
            if ("n" == field) {
                return Math.abs(Math.floor(diffMillis / (60 * 1000)));
            }

            // 计算毫秒数
            if ("s" == field) {
                return Math.abs(Math.floor(diffMillis / (1000)));
            }
        } else {
            throw Error("不支持的日期字段：" + field);
        }
    } else {
        throw Error("otherDate必须为Date类型！");
    }
};

/**
 * 输出带星期的日期字符串 ,比如2013-08-21 星期三
 *
 * @return 日期字符串，带星期
 */
Date.prototype.toStringWeek = function () {
    var week = ['日', '一', '二', '三', '四', '五', '六'];
    return this.getFullYear() + "-" + (this.getMonth() + 1) + "-" + this.getDate() + " " +
        this.getHours() + ":" + this.getMinutes() + ":" + this.getSeconds() + " 星期" + week[this.getDay()];
};

/**
 * 将日期对象转成数组，按照年月日时分秒存放，Array[0]为年，一次类推
 *
 * @return 日期数组
 */
Date.prototype.toArray = function () {
    var myDate = this;
    var myArray = Array();
    myArray[0] = myDate.getFullYear();
    myArray[1] = myDate.getMonth();
    myArray[2] = myDate.getDate();
    myArray[3] = myDate.getHours();
    myArray[4] = myDate.getMinutes();
    myArray[5] = myDate.getSeconds();
    return myArray;
};

/**
 * 获取日期指定字段的具体数值，类型part如下： y ：年； m ：月； w ：周； d ：日； h ：时； n ：分； s ：秒。
 *
 * @param field
 *            日期字段
 * @return 具体类型所对应的数组
 */
Date.prototype.dateField = function (field) {
    var myDate = this;
    var partStr = '';
    switch (field) {
        case 'y':
            partStr = myDate.getFullYear();
            break;
        case 'm':
            partStr = myDate.getMonth();
            break;
        case 'd':
            partStr = myDate.getDate();
            break;
        case 'w':
            var Week = ['日', '一', '二', '三', '四', '五', '六'];
            partStr = "星期" + Week[myDate.getDay()];
            break;
        case 'h':
            partStr = myDate.getHours();
            break;
        case 'n':
            partStr = myDate.getMinutes();
            break;
        case 's':
            partStr = myDate.getSeconds();
            break;
        default:
            throw Error("不支持的日期字段：" + field);
    }
    return partStr;
};

/**
 * 获取当日期所属月的天数，如1月为31天。
 *
 * @return 天数
 */
Date.prototype.maxDayOfMonth = function () {
    var monthNextFirstDay = new Date(this.getYear(), this.getMonth() + 1, 1);
    var monthLastDay = new Date(monthNextFirstDay - 86400000);
    return monthLastDay.getDate();
};

/**
 * 获取当前日期所在的周是一年中的第几周。每周开始于周日。
 *
 * @return 周次
 */
Date.prototype.weekOfYear = function () {

    // 获得当前日期是今年第多少天 dayOfYear
    // 用dayOfYear + 当前年的第一天的周差距的和在除以7就是本年第几周
    var year = this.getFullYear();
    var firstDay = new Date(year, 0, 1);
    var firstWeekDays = 7 - firstDay.getDay();
    var dayOfYear = (((new Date(year, this.getMonth(), this.getDate())) - firstDay) / (24 * 3600 * 1000)) + 1;
    return Math.ceil((dayOfYear - firstWeekDays) / 7) + 1;
};

/**
 * 获取当前日期所在年份的周数，如：52周
 *
 * @return 周数
 */
Date.prototype.weeks = function () {

    // 每年最后一天必然是12月31日，得到这天在这年所在的周数，就可以得到这年有多少周
    var date = new Date(this.getFullYear(), 11, 31);
    return date.weekOfYear();
};

/**
 * 获取当前日期属于第几季度
 *
 * @return 季度 1：META-INF ； 2：summer ； 3：autumn ； 4：winter
 */
Date.prototype.quarterOfYear = function () {
    var currMonth = this.getMonth() + 1;
    return Math.floor(currMonth % 3 == 0 ? ( currMonth / 3 ) : ( currMonth / 3 + 1 ));
};
